home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Games / WormWars / Source / FE.C < prev    next >
C/C++ Source or Header  |  2002-10-16  |  36KB  |  984 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/alerts.h>
  4.  
  5. #include "diff.h"
  6. #include "same.h"
  7. #include "amiga.h"
  8.  
  9. #include <intuition/intuition.h> // for struct Window, etc.
  10. #include <libraries/gadtools.h>  // for GT_VisualInfo, etc.
  11.  
  12. #include <stdlib.h>              // for EXIT_SUCCESS, etc.
  13.  
  14. MODULE UWORD chip CustomPointer[] =
  15. {   0x0000, 0x0000, /* reserved */
  16.  
  17.     0xF800, 0xFC00, /* 1st row 1st plane, 1st row 2nd plane */
  18.     0xF800, 0x8400, /* 2nd row 1st plane, 2nd row 2nd plane */
  19.     0xF800, 0x8400, /* 3rd row 1st plane, 3rd row 2nd plane */
  20.     0xF800, 0x8400, /* 4th row 1st plane, 4th row 2nd plane */
  21.     0xF800, 0x8400, /* 5th row 1st plane, 5th row 2nd plane */
  22.     0x8000, 0xFC00, /* 6th row 1st plane, 6th row 2nd plane */
  23.  
  24.     0x0000, 0x0000  /* reserved */
  25.  
  26. /*  11111000-------- 11111100--------
  27.     11111000-------- 10000100--------
  28.     11111000-------- 10000100--------
  29.     11111000-------- 10000100--------
  30.     11111000-------- 10000100--------
  31.     10000000-------- 11111100-------- */
  32.  
  33. };
  34.  
  35. #define ALTJUMP         5
  36.  
  37. /* pseudo-gadgets */
  38. #define GADGETX         (-2) // negatives must be within parentheses
  39. #define EMPTYGADGET    ((FIELDY / 2) - 7)
  40. #define SILVERGADGET   ((FIELDY / 2) - 5)
  41. #define GOLDGADGET     ((FIELDY / 2) - 3)
  42. #define DYNAMITEGADGET ((FIELDY / 2) - 1)
  43. #define WOODGADGET     ((FIELDY / 2) + 1)
  44. #define STONEGADGET    ((FIELDY / 2) + 3)
  45. #define METALGADGET    ((FIELDY / 2) + 5)
  46. #define FROSTGADGET    ((FIELDY / 2) + 7)
  47.  
  48. MODULE void setpointer(UBYTE brush);
  49. MODULE void dot(void);
  50. MODULE void undot(void);
  51. MODULE void stamp(UBYTE square);
  52. MODULE void fillfield(UBYTE which);
  53. MODULE void underline(UBYTE square);
  54. MODULE SBYTE xpixeltosquare(SWORD x);
  55. MODULE SBYTE ypixeltosquare(SWORD y);
  56. MODULE void levelappend(void);
  57. MODULE void leveldelete(void);
  58. MODULE void levelerase(void);
  59. MODULE void levelinsert(void);
  60. MODULE void copyfield(UBYTE source, UBYTE destination);
  61.  
  62. IMPORT struct Window*        MainWindowPtr;
  63. IMPORT struct Menu*          MenuPtr;
  64. IMPORT struct VisualInfo*    VisualInfoPtr;
  65. IMPORT struct timerequest*   TimerRqPtr;
  66. IMPORT struct InputEvent     GameEvent;
  67. IMPORT struct Screen*        ScreenPtr;
  68.  
  69. IMPORT struct TeleportStruct teleport[MAXLEVELS + 1][4];
  70.  
  71. IMPORT ABOOL               anims,
  72.                            clearthem,
  73.                            icons,
  74.                            modified,
  75.                            thick;
  76. IMPORT SBYTE               a,
  77.                            board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  78.                            startx[MAXLEVELS + 1],
  79.                            starty[MAXLEVELS + 1],
  80.                            fex = FIELDX / 2,
  81.                            fey = FIELDY / 2,
  82.                            level, levels;
  83.  
  84. MODULE ABOOL               sticky = FALSE;
  85. MODULE UBYTE               brush  = STONE;
  86.  
  87. AGLOBAL void fieldedit(void)
  88. {   AUTO    ABOOL                leftdown  = FALSE,
  89.                                  timer     = FALSE;
  90.     AUTO    SBYTE                pointerx, pointery,
  91.                                  which,
  92.                                  x, y;
  93.     AUTO    SWORD                mousex, mousey;
  94.     AUTO    UWORD                code, qual;
  95.     AUTO    ULONG                class;
  96.     AUTO    struct IntuiMessage* MsgPtr;
  97.     AUTO    struct MenuItem*     ItemPtr;
  98.     PERSIST ABOOL                clipboarded = FALSE;
  99.     PERSIST UBYTE                clipboard[FIELDX + 1][FIELDY + 1];
  100.  
  101.     say("Field Editor", WHITE);
  102.     setpointer(brush);
  103.     if (level > levels)
  104.         level = levels;
  105.     OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  106.     if (!clipboarded)
  107.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  108.  
  109.     /* draw pseudo-gadgets */
  110.     
  111.     clearscreen();
  112.     for (which = 0; which <= 7; which++)
  113.     {   DrawBevelBox
  114.         (   MainWindowPtr->RPort,
  115.             STARTXPIXEL - (SQUAREX * 2) - 4,
  116.             156 + (which * 2 * SQUAREY), // -12 per new gadget added
  117.             SQUAREX + 8,
  118.             SQUAREY + 8,
  119.             GT_VisualInfo, VisualInfoPtr,
  120.             TAG_DONE
  121.         );
  122.     }
  123.     SetAPen(MainWindowPtr->RPort, WHITE);
  124.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   EMPTYGADGET * SQUAREY));
  125.     Text(MainWindowPtr->RPort, "F1:", 3);
  126.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (  SILVERGADGET * SQUAREY));
  127.     Text(MainWindowPtr->RPort, "F2:", 3);
  128.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    GOLDGADGET * SQUAREY));
  129.     Text(MainWindowPtr->RPort, "F3:", 3);
  130.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (DYNAMITEGADGET * SQUAREY));
  131.     Text(MainWindowPtr->RPort, "F4:", 3);
  132.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    WOODGADGET * SQUAREY));
  133.     Text(MainWindowPtr->RPort, "F5:", 3);
  134.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   STONEGADGET * SQUAREY));
  135.     Text(MainWindowPtr->RPort, "F6:", 3);
  136.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   METALGADGET * SQUAREY));
  137.     Text(MainWindowPtr->RPort, "F7:", 3);
  138.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   FROSTGADGET * SQUAREY));
  139.     Text(MainWindowPtr->RPort, "F8:", 3);
  140.  
  141.     draw(GADGETX,    EMPTYGADGET,    EMPTY);
  142.     draw(GADGETX,   SILVERGADGET,   SILVER);
  143.     draw(GADGETX,     GOLDGADGET,     GOLD);
  144.     draw(GADGETX, DYNAMITEGADGET, DYNAMITE);
  145.     draw(GADGETX,     WOODGADGET,     WOOD);
  146.     draw(GADGETX,    STONEGADGET,    STONE);
  147.     draw(GADGETX,    METALGADGET,    METAL);
  148.     draw(GADGETX,    FROSTGADGET,    FROST);
  149.  
  150.     underline(brush);
  151.     turborender();
  152.     saylevel(WHITE);
  153.     clearkybd();
  154.  
  155.     fex = startx[level];
  156.     fey = starty[level];
  157.     dot();
  158.  
  159.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | IDCMP_REFRESHWINDOW | IDCMP_MOUSEMOVE)))
  160.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  161.     cleanexit(EXIT_FAILURE);
  162.     }
  163.     while (a == FIELDEDIT)
  164.     {   Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  165.         while (MsgPtr = GT_GetIMsg(MainWindowPtr->UserPort))
  166.         {   class  = MsgPtr->Class;
  167.             code   = MsgPtr->Code;
  168.             qual   = MsgPtr->Qualifier;
  169.             mousex = MsgPtr->MouseX;
  170.             mousey = MsgPtr->MouseY;
  171.             if (class == IDCMP_MENUVERIFY)
  172.             {   if
  173.                 (   mousex >= STARTXPIXEL
  174.                  && mousex <=   ENDXPIXEL
  175.                  && mousey >= STARTYPIXEL
  176.                  && mousey <=   ENDYPIXEL
  177.                 )
  178.                 {   MsgPtr->Code = MENUCANCEL;
  179.             }   }
  180.             GT_ReplyIMsg(MsgPtr);
  181.             switch (class)
  182.             {
  183.             case IDCMP_MOUSEMOVE:
  184.                 if (leftdown)
  185.                 {   pointerx = xpixeltosquare(mousex);
  186.                     pointery = ypixeltosquare(mousey);
  187.                     if
  188.                     (   (pointerx != fex || pointery != fey)
  189.                      && valid(pointerx, pointery)
  190.                     )
  191.                     {   undot();
  192.                         fex = pointerx;
  193.                         fey = pointery;
  194.                         stamp(brush);
  195.                 }   }
  196.             break;
  197.             case IDCMP_MENUPICK:
  198.                 while (code != MENUNULL)
  199.                 {   ItemPtr = ItemAddress(MenuPtr, code);
  200.                     switch (MENUNUM(code))
  201.                     {
  202.                     case MN_PROJECT:
  203.                         switch (ITEMNUM(code))
  204.                         {
  205.                         case IN_NEW:
  206.                             newfields();
  207.                             say("New done.", WHITE);
  208.                         break;
  209.                         case IN_OPEN:
  210.                             fileopen(FALSE);
  211.                         break;
  212.                         case IN_REVERT:
  213.                             fileopen(TRUE);
  214.                         break;
  215.                         case IN_SAVE:
  216.                             if (modified)
  217.                             {   clearhiscores();
  218.                                 modified = FALSE;
  219.                             }
  220.                             filesaveas(FALSE);
  221.                             turborender();
  222.                         break;
  223.                         case IN_SAVEAS:
  224.                             if (modified)
  225.                             {   clearhiscores();
  226.                                 modified = FALSE;
  227.                             }
  228.                             filesaveas(TRUE);
  229.                             turborender();
  230.                         break;
  231.                         case IN_PROJECTDELETE:
  232.                             filedelete();
  233.                         break;
  234.                         case IN_QUIT:
  235.                             if (verify())
  236.                                 cleanexit(EXIT_SUCCESS);
  237.                         break;
  238.                         default:
  239.                         break;
  240.                         }
  241.                     break;
  242.                     case MN_EDIT:
  243.                         switch (ITEMNUM(code))
  244.                         {
  245.                         case IN_CUT:
  246.                             for (x = 0; x <= FIELDX; x++)
  247.                                 for (y = 0; y <= FIELDY; y++)
  248.                                     clipboard[x][y] = board[level][x][y];
  249.                             leveldelete();
  250.                             clipboarded = TRUE;
  251.                             modified = TRUE;
  252.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  253.                         break;
  254.                         case IN_COPY:
  255.                             for (x = 0; x <= FIELDX; x++)
  256.                                 for (y = 0; y <= FIELDY; y++)
  257.                                     clipboard[x][y] = board[level][x][y];
  258.                             clipboarded = TRUE;
  259.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  260.                         break;
  261.                         case IN_PASTE:
  262.                             for (x = 0; x <= FIELDX; x++)
  263.                                 for (y = 0; y <= FIELDY; y++)
  264.                                     board[level][x][y] = clipboard[x][y];
  265.                             turborender();
  266.                             modified = TRUE;
  267.                         break;
  268.                         case IN_ERASE:
  269.                             levelerase();
  270.                         break;
  271.                         case IN_INSERT:
  272.                             levelinsert();
  273.                         break;
  274.                         case IN_EDITDELETE:
  275.                             leveldelete();
  276.                         break;
  277.                         case IN_APPEND:
  278.                             levelappend();
  279.                         break;
  280.                         default:
  281.                         break;
  282.                         }
  283.                     break;
  284.                     case MN_SETTINGS:
  285.                         switch(ITEMNUM(code))
  286.                         {
  287.                         case IN_ANIMATIONS:
  288.                             if (ItemPtr->Flags & CHECKED)
  289.                             {   anims = TRUE;
  290.                             } else
  291.                             {   anims = FALSE;
  292.                             }
  293.                         break;
  294.                         case IN_CREATEICONS:
  295.                             if (ItemPtr->Flags & CHECKED)
  296.                             {   icons = TRUE;
  297.                             } else
  298.                             {   icons = FALSE;
  299.                             }
  300.                         break;
  301.                         case IN_THICKTAILS:
  302.                             if (ItemPtr->Flags & CHECKED)
  303.                             {   thick = TRUE;
  304.                             } else
  305.                             {   thick = FALSE;
  306.                             }
  307.                         break;
  308.                         default:
  309.                         break;
  310.                         }
  311.                     break;
  312.                     case MN_HELP:
  313.                         switch(ITEMNUM(code))
  314.                         {
  315.                         case IN_CREATURES:
  316.                             help(ORB);
  317.                         break;
  318.                         case IN_OBJECTS:
  319.                             help(AFFIXER);
  320.                         break;
  321.                         case IN_ABOUT:
  322.                             helpabout();
  323.                         break;
  324.                         default:
  325.                         break;
  326.                         }
  327.                     break;
  328.                     default:
  329.                     break;
  330.                     } // hctiws
  331.                     code = ItemPtr->NextSelect;
  332.                 } // elihw
  333.             break;
  334.             case IDCMP_RAWKEY:
  335.                 if (!(qual & IEQUALIFIER_REPEAT))
  336.                 {   effect(FXCLICK);
  337.                 }
  338.                 switch(code)
  339.                 {
  340.                 case DELETE:
  341.                     if (!(qual & IEQUALIFIER_REPEAT))
  342.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  343.                             level = 1;
  344.                         elif (--level < 0)
  345.                             level = levels;
  346.                         saylevel(WHITE);
  347.                         turborender();
  348.                     }
  349.                 break;
  350.                 case HELP:
  351.                     if (!(qual & IEQUALIFIER_REPEAT))
  352.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  353.                             level = levels;
  354.                         elif (++level > levels)
  355.                             level = 0;
  356.                         saylevel(WHITE);
  357.                         turborender();
  358.                     }
  359.                 break;
  360.                 case M:
  361.                     if (!(qual & IEQUALIFIER_REPEAT))
  362.                         toggle(M);
  363.                 break;
  364.                 case F:
  365.                     if (!(qual & IEQUALIFIER_REPEAT))
  366.                         toggle(F);
  367.                 break;
  368.                 case ESCAPE:
  369.                     if (!(qual & IEQUALIFIER_REPEAT))
  370.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  371.                         {   if (verify())
  372.                             {   cleanexit(EXIT_SUCCESS);
  373.                         }   }
  374.                         else
  375.                         {   a = GAMEOVER;
  376.                     }   }
  377.                 break;
  378.                 case SPACEBAR:
  379.                 case RETURN:
  380.                 case ENTER:
  381.                     if (!(qual & IEQUALIFIER_REPEAT))
  382.                         a = GAMEOVER;
  383.                 break;
  384.                 case NUMERICOPEN:
  385.                     setpointer(NORMAL);
  386.                     underline(255);
  387.  
  388.                     brush--;
  389.                     if (brush <= 0 || brush > LASTOBJECT) // note sign issues
  390.                     {   brush = LASTOBJECT;
  391.                     }   stamp(brush);
  392.                 break;
  393.                 case NUMERICCLOSE:
  394.                     setpointer(NORMAL);
  395.                     underline(255);
  396.  
  397.                     brush++;
  398.                     if (brush > LASTOBJECT)
  399.                     {   brush = 0;
  400.                         stamp(brush);
  401.                     }
  402.                 break;
  403.                 case C:
  404.                     effect(FXCENTRE); /* interesting */
  405.                     undot();
  406.                     fex = FIELDX / 2;
  407.                     fey = FIELDY / 2;
  408.                     dot();
  409.                 break;
  410.                 case S:
  411.                     stamp(START);
  412.                 break;
  413.                 case KEY_T:
  414.                     stamp(TELEPORT);
  415.                 break;
  416.                 case KEY_U:
  417.                     stamp(ARROWUP);
  418.                 break;
  419.                 case D:
  420.                     stamp(ARROWDOWN);
  421.                 break;
  422.                 case O:
  423.                     stamp(OCTOPUS);
  424.                 break;
  425.                 case ALPHAONE:
  426.                     stamp(EMPTY);
  427.                 break;
  428.                 case ALPHATWO:
  429.                     stamp(SILVER);
  430.                 break;
  431.                 case ALPHATHREE:
  432.                     stamp(GOLD);
  433.                 break;
  434.                 case ALPHAFOUR:
  435.                     stamp(DYNAMITE);
  436.                 break;
  437.                 case ALPHAFIVE:
  438.                     stamp(WOOD);
  439.                 break;
  440.                 case ALPHASIX:
  441.                     stamp(STONE);
  442.                 break;
  443.                 case ALPHASEVEN:
  444.                     stamp(METAL);
  445.                 break;
  446.                 case ALPHAEIGHT:
  447.                     stamp(FROST);
  448.                 break;
  449.                 case F1:
  450.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  451.                     {   fillfield(EMPTY);
  452.                     } else setbrush(EMPTY);
  453.                 break;
  454.                 case F2:
  455.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  456.                     {   fillfield(SILVER);
  457.                     } else setbrush(SILVER);
  458.                 break;
  459.                 case F3:
  460.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  461.                     {   fillfield(GOLD);
  462.                     } else setbrush(GOLD);
  463.                 break;
  464.                 case F4:
  465.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  466.                     {   fillfield(DYNAMITE);
  467.                     } else setbrush(DYNAMITE);
  468.                 break;
  469.                 case F5:
  470.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  471.                     {   fillfield(WOOD);
  472.                     } else setbrush(WOOD);
  473.                 break;
  474.                 case F6:
  475.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  476.                     {   fillfield(STONE);
  477.                     } else setbrush(STONE);
  478.                 break;
  479.                 case F7:
  480.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  481.                     {   fillfield(METAL);
  482.                     } else setbrush(METAL);
  483.                 break;
  484.                 case F8:
  485.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  486.                     {   fillfield(FROST);
  487.                     } else setbrush(FROST);
  488.                 break;
  489.                 case NUMERICZERO:
  490.                     if (!(qual & IEQUALIFIER_REPEAT))
  491.                     {   if (!sticky)
  492.                         {   sticky = TRUE;
  493.                             say("Sticky mode on", WHITE);
  494.                             stamp(brush);
  495.                         } else
  496.                         {   sticky = FALSE;
  497.                             say("Sticky mode off", WHITE);
  498.                             dot();
  499.                     }   }
  500.                 break;
  501.                 case NUMERICDOT:
  502.                     stamp(brush);
  503.                 break;
  504.                 case KEY_X:
  505.                     undot();
  506.                     fex = FIELDX - fex;
  507.                     dot();
  508.                 break;
  509.                 case KEY_Y:
  510.                     undot();
  511.                     fey = FIELDY - fey;
  512.                     dot();
  513.                 break;
  514.                 case NUMERICFOUR:
  515.                 case LEFT:
  516.                     undot();
  517.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  518.                     {   fex = 0;
  519.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  520.                     {   fex = xwrap(fex - ALTJUMP);
  521.                     } else
  522.                     {   fex = xwrap(fex - 1);
  523.                     }
  524.                     if (sticky)
  525.                     {   stamp(brush);
  526.                     } else
  527.                     {   dot();
  528.                     }
  529.                 break;
  530.                 case NUMERICSIX:
  531.                 case RIGHT:
  532.                     undot();
  533.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  534.                     {   fex = FIELDX;
  535.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  536.                     {   fex = xwrap(fex + ALTJUMP);
  537.                     } else
  538.                     {   fex = xwrap(fex + 1);
  539.                     }
  540.                     if (sticky)
  541.                     {   stamp(brush);
  542.                     } else
  543.                     {   dot();
  544.                     }
  545.                 break;
  546.                 case NUMERICEIGHT:
  547.                 case UP:
  548.                     undot();
  549.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  550.                     {   fey = 0;
  551.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  552.                     {   fey = ywrap(fey - ALTJUMP);
  553.                     } else
  554.                     {   fey = ywrap(fey - 1);
  555.                     }
  556.                     if (sticky)
  557.                     {   stamp(brush);
  558.                     } else
  559.                     {   dot();
  560.                     }
  561.                 break;
  562.                 case NUMERICFIVE:
  563.                 case NUMERICTWO:
  564.                 case DOWN:
  565.                     undot();
  566.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  567.                     {   fey = FIELDY;
  568.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  569.                     {   fey = ywrap(fey + ALTJUMP);
  570.                     } else
  571.                     {   fey = ywrap(fey + 1);
  572.                     }
  573.                     if (sticky)
  574.                     {   stamp(brush);
  575.                     } else
  576.                     {   dot();
  577.                     }
  578.                 break;
  579.                 case NUMERICSEVEN:
  580.                     undot();
  581.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  582.                     {   fex = 0;
  583.                         fey = 0;
  584.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  585.                     {   fex = xwrap(fex - ALTJUMP);
  586.                         fey = ywrap(fey - ALTJUMP);
  587.                     } else
  588.                     {   fex = xwrap(fex - 1);
  589.                         fey = ywrap(fey - 1);
  590.                     }
  591.                     if (sticky)
  592.                     {   stamp(brush);
  593.                     } else
  594.                     {   dot();
  595.                     }
  596.                 break;
  597.                 case NUMERICNINE:
  598.                     undot();
  599.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  600.                     {   fex = FIELDX;
  601.                         fey = 0;
  602.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  603.                     {   fex = xwrap(fex + ALTJUMP);
  604.                         fey = ywrap(fey - ALTJUMP);
  605.                     } else
  606.                     {   fex = xwrap(fex + 1);
  607.                         fey = ywrap(fey - 1);
  608.                     }
  609.                     if (sticky)
  610.                     {   stamp(brush);
  611.                     } else
  612.                     {   dot();
  613.                     }
  614.                 break;
  615.                 case NUMERICONE:
  616.                     undot();
  617.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  618.                     {   fex = 0;
  619.                         fey = FIELDY;
  620.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  621.                     {   fex = xwrap(fex - ALTJUMP);
  622.                         fey = ywrap(fey + ALTJUMP);
  623.                     } else
  624.                     {   fex = xwrap(fex - 1);
  625.                         fey = ywrap(fey + 1);
  626.                     }
  627.                     if (sticky)
  628.                     {   stamp(brush);
  629.                     } else
  630.                     {   dot();
  631.                     }
  632.                 break;
  633.                 case NUMERICTHREE:
  634.                     undot();
  635.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  636.                     {   fex = FIELDX;
  637.                         fey = FIELDY;
  638.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  639.                     {   fex = xwrap(fex + ALTJUMP);
  640.                         fey = ywrap(fey + ALTJUMP);
  641.                     } else
  642.                     {   fex = xwrap(fex + 1);
  643.                         fey = ywrap(fey + 1);
  644.                     }
  645.                     if (sticky)
  646.                     {   stamp(brush);
  647.                     } else
  648.                     {   dot();
  649.                     }
  650.                 break;
  651.                 default:
  652.                 break;
  653.                 } // hctiws
  654.             break;
  655.             case IDCMP_MOUSEBUTTONS:
  656.                 if (code == SELECTDOWN)
  657.                 {   pointerx = xpixeltosquare(mousex);
  658.                     pointery = ypixeltosquare(mousey);
  659.                     leftdown = TRUE;
  660.                     if (pointerx == GADGETX)
  661.                     {   switch (pointery)
  662.                         {
  663.                         case GOLDGADGET:
  664.                             setbrush(GOLD);
  665.                         break;
  666.                         case SILVERGADGET:
  667.                             setbrush(SILVER);
  668.                         break;
  669.                         case EMPTYGADGET:
  670.                             setbrush(EMPTY);
  671.                         break;
  672.                         case WOODGADGET:
  673.                             setbrush(WOOD);
  674.                         break;
  675.                         case DYNAMITEGADGET:
  676.                             setbrush(DYNAMITE);
  677.                         break;
  678.                         case STONEGADGET:
  679.                             setbrush(STONE);
  680.                         break;
  681.                         case METALGADGET:
  682.                             setbrush(METAL);
  683.                         break;
  684.                         case FROSTGADGET:
  685.                             setbrush(FROST);
  686.                         break;
  687.                         default:
  688.                         break;
  689.                     }   }
  690.                     else
  691.                     {   if (valid(pointerx, pointery))
  692.                         {   undot();
  693.                             fex = pointerx;
  694.                             fey = pointery;
  695.                             stamp(brush);
  696.                 }   }   }
  697.                 elif (code == SELECTUP)
  698.                 {   leftdown = FALSE;
  699.                 } elif (code == MENUUP)
  700.                 {   pointerx = xpixeltosquare(mousex);
  701.                     pointery = ypixeltosquare(mousey);
  702.                     if (valid(pointerx, pointery))
  703.                     {   undot();
  704.                         fex = pointerx;
  705.                         fey = pointery;
  706.                         stamp(EMPTY);
  707.                 }   }
  708.             break;
  709.             case IDCMP_CLOSEWINDOW:
  710.                 cleanexit(EXIT_SUCCESS);
  711.             break;
  712.             case IDCMP_REFRESHWINDOW:
  713.                 GT_BeginRefresh(MainWindowPtr);
  714.                 GT_EndRefresh(MainWindowPtr, TRUE);
  715.             break;
  716.             default:
  717.                 /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS, IDCMP_ACTIVEWINDOW */
  718.             break;
  719.     }   }   }
  720.  
  721.     /* exit to title screen */
  722.  
  723.     if (!(ModifyIDCMP(MainWindowPtr->RPort, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS)))
  724.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  725.     cleanexit(EXIT_FAILURE);
  726.     }
  727.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  728.     if (timer)
  729.     {   AbortIO((struct IORequest *) TimerRqPtr);
  730.          WaitIO((struct IORequest *) TimerRqPtr);
  731.     }
  732.     setpointer(NORMAL);
  733.     if (clearthem)
  734.         clearhiscores();
  735.     matchteleports();
  736. }
  737.  
  738. MODULE void stamp(UBYTE square)
  739. {   if (square == START)
  740.     {   draw(startx[level], starty[level], EMPTY);
  741.         board[level][startx[level]][starty[level]] = EMPTY;
  742.         startx[level] = fex;
  743.         starty[level] = fey;
  744.         board[level][fex][fey] = EMPTY;
  745.     } else
  746.     {   board[level][fex][fey] = square;
  747.     }
  748.  
  749.     draw(fex, fey, square);
  750.     dot();
  751.     modified = clearthem = TRUE;
  752. }
  753.  
  754. MODULE void undot(void)
  755. {   if (startx[level] == fex && starty[level] == fey)
  756.         draw(fex, fey, START);
  757.     else draw(fex, fey, board[level][fex][fey]);
  758. }
  759.  
  760. MODULE void fillfield(UBYTE which)
  761. {   SBYTE x, y;
  762.  
  763.     // Service routine for field editor.
  764.  
  765.     for (x = 0; x <= FIELDX; x++)
  766.     {   for (y = 0; y <= FIELDY; y++)
  767.         {   board[level][x][y] = which;
  768.             draw(x, y, which);
  769.     }   }
  770.     board[level][startx[level]][starty[level]] = EMPTY;
  771.     draw(startx[level], starty[level], START);
  772.     dot();
  773. }
  774.  
  775. AGLOBAL void setbrush(UBYTE newbrush)
  776. {   brush = newbrush;
  777.     setpointer(brush);
  778.     underline(brush);
  779. }
  780.  
  781. MODULE void underline(UBYTE square)
  782. {   /* Removes old underline, draws new underline.
  783.  
  784.     square: which square-type to underline, or 255 for clear only.
  785.     Squares which do not correspond to any pseudo-gadgets
  786.     (eg. objects) are converted to 255s. */
  787.  
  788.     PERSIST SWORD oldy = 255;
  789.     AUTO    SWORD y;
  790.  
  791.     switch(square)
  792.     {
  793.     case EMPTY:
  794.         y = STARTYPIXEL + (EMPTYGADGET * SQUAREY);
  795.     break;
  796.     case SILVER:
  797.         y = STARTYPIXEL + (SILVERGADGET * SQUAREY);
  798.     break;
  799.     case GOLD:
  800.         y = STARTYPIXEL + (GOLDGADGET * SQUAREY);
  801.     break;
  802.     case DYNAMITE:
  803.         y = STARTYPIXEL + (DYNAMITEGADGET * SQUAREY);
  804.     break;
  805.     case WOOD:
  806.         y = STARTYPIXEL + (WOODGADGET * SQUAREY);
  807.     break;
  808.     case STONE:
  809.         y = STARTYPIXEL + (STONEGADGET * SQUAREY);
  810.     break;
  811.     case METAL:
  812.         y = STARTYPIXEL + (METALGADGET * SQUAREY);
  813.     break;
  814.     default:
  815.         square = 255;
  816.         y = 0; // to avoid spurious warnings
  817.     break;
  818.     }
  819.  
  820.     if (oldy != 255)
  821.     {   SetAPen(MainWindowPtr->RPort, BLACK);
  822.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy);
  823.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy + SQUAREY);
  824.     }
  825.     if (square != 255)
  826.     {   SetAPen(MainWindowPtr->RPort, WHITE);
  827.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, y);
  828.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, y + SQUAREY);
  829.         oldy = y;
  830. }   }
  831.  
  832. MODULE void dot(void)
  833. {   SWORD x, xx, y, yy;
  834.  
  835.     /* Squares are dotted as follows:
  836.     
  837.          012345678901
  838.         0............
  839.         1............
  840.         2............
  841.         3............
  842.         4....WWW.....
  843.         5....WWWB....
  844.         6....WWWB....
  845.         7.....BBB....
  846.         8............
  847.         9............
  848.        10............
  849.        11............ */
  850.  
  851.     xx = (fex * SQUAREX) + STARTXPIXEL;
  852.     yy = (fey * SQUAREY) + STARTYPIXEL;
  853.  
  854.     if (sticky)
  855.         SetAPen(MainWindowPtr->RPort, RED);
  856.     else SetAPen(MainWindowPtr->RPort, WHITE);
  857.         for (x = 4; x <= 6; x++)
  858.         {   for (y = 4; y <= 6; y++)
  859.             {   WritePixel(MainWindowPtr->RPort, xx + x, yy + y);
  860.         }   }
  861.         SetAPen(MainWindowPtr->RPort, BLACK);
  862.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 5);
  863.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 6);
  864.         WritePixel(MainWindowPtr->RPort, xx + 5, yy + 7);
  865.         WritePixel(MainWindowPtr->RPort, xx + 6, yy + 7);
  866.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 7);
  867. }
  868.  
  869. MODULE void setpointer(UBYTE pointer)
  870. {   switch (pointer)
  871.     {
  872.     case EMPTY:
  873.         SetRGB4(&ScreenPtr->ViewPort, 17,  2,  2,  2);          /* fill */
  874.         SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);          /* shadow */
  875.         SetRGB4(&ScreenPtr->ViewPort, 19,  2,  2,  2);          /* shine */
  876.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  877.     break;
  878.     case DYNAMITE:
  879.         SetRGB4(&ScreenPtr->ViewPort, 17, 15,  8, 15);          /* fill */
  880.         SetRGB4(&ScreenPtr->ViewPort, 18, 15,  8, 15);          /* shadow */
  881.         SetRGB4(&ScreenPtr->ViewPort, 19, 15,  8, 15);          /* shine */
  882.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  883.     break;
  884.     case WOOD:
  885.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        /* fill */
  886.         SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);          /* shadow */
  887.         SetRGB4(&ScreenPtr->ViewPort, 19,  8,  4,  2);          /* shine */
  888.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  889.     break;
  890.     case STONE:
  891.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        /* fill */
  892.         SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);          /* shadow */
  893.         SetRGB4(&ScreenPtr->ViewPort, 19,  0,  0,  0);          /* shine */
  894.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  895.     break;
  896.     case METAL:
  897.         SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10, 10);          /* fill */
  898.         SetRGB4(&ScreenPtr->ViewPort, 18, 10, 10, 10);          /* shadow */
  899.         SetRGB4(&ScreenPtr->ViewPort, 19, 10, 10, 10);          /* shine */
  900.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  901.     break;
  902.     case FROST:
  903.         SetRGB4(&ScreenPtr->ViewPort, 17, 12, 12, 15);          /* fill */
  904.         SetRGB4(&ScreenPtr->ViewPort, 18, 12, 12, 15);          /* shadow */
  905.         SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 15);          /* shine */
  906.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  907.     break;
  908.     default:
  909.         SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4); /* fill */
  910.         SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3); /* shadow */
  911.         SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12); /* shine */
  912.     ClearPointer(MainWindowPtr);
  913.     break;
  914. }   }
  915.  
  916. MODULE SBYTE xpixeltosquare(SWORD x)
  917. {   x = (x - STARTXPIXEL) / SQUAREX;
  918.     if (x < 0)
  919.         x--;
  920.     return ((SBYTE) x);
  921. }
  922. MODULE SBYTE ypixeltosquare(SWORD y)
  923. {   y = (y - STARTYPIXEL) / SQUAREY;
  924.     if (y < 0)
  925.         y--;
  926.     return ((SBYTE) y);
  927. }
  928.  
  929. MODULE void levelappend(void)
  930. {   UBYTE oldlevel;
  931.  
  932.     if (levels < MAXLEVELS)
  933.     {   oldlevel = level;
  934.         level = ++levels;
  935.         newfield();
  936.         level = oldlevel;
  937.         saylevel(WHITE);
  938. }   }
  939. MODULE void leveldelete(void)
  940. {   SBYTE i;
  941.  
  942.     /* pull boards */
  943.  
  944.     if (levels > 1)
  945.     {   if (level < levels)
  946.         for (i = level; i < levels; i++)
  947.             copyfield(i + 1, i);
  948.         else
  949.             level--;
  950.         levels--;
  951.         saylevel(WHITE);
  952.         turborender();
  953. }   }
  954. MODULE void levelerase(void)
  955. {   newfield();
  956.     turborender();
  957. }
  958. MODULE void levelinsert(void)
  959. {   UBYTE i;
  960.  
  961.     /* push boards */
  962.  
  963.     if (levels < MAXLEVELS)
  964.     {   for (i = levels; i >= level; i--)
  965.             copyfield(i, i + 1);
  966.         levels++;
  967.         saylevel(WHITE);
  968.         newfield();
  969.         turborender();
  970. }   }
  971. MODULE void copyfield(UBYTE source, UBYTE destination)
  972. {   SBYTE which, x, y;
  973.  
  974.     for (x = 0; x <= FIELDX; x++)
  975.         for (y = 0; y <= FIELDY; y++)
  976.             board[destination][x][y] = board[source][x][y];
  977.     startx[destination] = startx[source];
  978.     starty[destination] = starty[source];
  979.     for (which = 0; which <= 1; which++)
  980.     {   teleport[destination][which].alive = teleport[source][which].alive;
  981.         teleport[destination][which].x     = teleport[source][which].x;
  982.         teleport[destination][which].y     = teleport[source][which].y;
  983. }   }
  984.